package drunkensailor.framework;

import drunkensailor.framework.support.DSLevel;
import drunkensailor.framework.support.Map;
import drunkensailor.framework.support.exceptions.InvalidMoveException;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import java.io.IOException;;

public class Simulation {

	private Sailor sailor;
	private ArrayList<Map> maps;
	private Logger logger = Logger.getLogger("SailorLog");
	private FileHandler fh;
	private Level logLevel;
	public static DSLevel sailorInfoLevel = new DSLevel("SIMULATION", 850);
	
	public Simulation(Sailor sailor, Level logLevel)
	{
		this.sailor = sailor;
		maps = new ArrayList<Map>();
		this.logLevel = logLevel;
		
		try{
			fh = new FileHandler("logs\\SailorLog.log", true);
			logger.addHandler(fh);
			logger.setLevel(logLevel);
			SimpleFormatter formatter = new SimpleFormatter();
			fh.setFormatter(formatter);
		}
		catch (SecurityException e){
			e.printStackTrace();
		}
		catch (IOException e){
			e.printStackTrace();
		}
		loadMaps();
	}
	
	private void loadMaps()
	{
		File folder = new File("maps/");
		File[] listOfFiles = folder.listFiles();
		for(File file : listOfFiles)
		{
			if(file.isFile())
			{
				logger.info("Adding map to maps array:  " + file.getName());
				maps.add(new Map(file.getName(), logLevel));
			}
		}
	}
	
	public void runSim()
	{
		logger.info("Starting to run all simulations.");
		for(Map toRun : maps)
			try {
				runSim(toRun.getMapName());
			} catch (FileNotFoundException e) {
				logger.logp(Level.WARNING, "Simulation", "runSim()", "Could not find specified map in maps. ", e);
				//e.printStackTrace();
			}
	}
	
	public boolean runSim(String mapName) throws FileNotFoundException
	{
		Map activeMap = null;
		
		for(Map t : maps)
		{
			if(t.getMapName().equals(mapName))
			{
				activeMap = t;
				break;
			}
		}
		
		if(activeMap == null)
			throw new FileNotFoundException();
		
		logger.info("Running sim on map " + activeMap.getMapName());
		
		int turns = 0;
		double distTraveled = 0.0;
		
		while(turns < 1000)
		{
			turns++;
			logger.log(Simulation.sailorInfoLevel, "Current Turn:  " + turns);
			
			
			Directions dirToMove = sailor.navigate(activeMap.getSurroundings(), activeMap.getDirectionToShip());
			logger.log(Simulation.sailorInfoLevel, "Sailor decided to move in direction " + dirToMove);
			try {
				if(activeMap.willInterceptShip(dirToMove))
				{
					if(dirToMove == Directions.NORTHWEST || dirToMove == Directions.NORTHEAST || dirToMove == Directions.SOUTHEAST || dirToMove == Directions.SOUTHWEST)
						distTraveled+=Math.sqrt(2.0);
					else
						distTraveled+=1.0;
					System.out.println("Success!  Your sailor made it back to the ship!  Here're the details:  ");
					System.out.println("--------------------------------------------------------------------------");
					System.out.println("Turns used:  " + turns);
					System.out.println("Distance Traveled:  " + distTraveled);
					System.out.println("\n-=-=-=-=-=-=-=-=-=-=-=-=-=-=-Map View-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=");
					System.out.println(activeMap.toString());
					logger.log(Simulation.sailorInfoLevel, "Simulation " + activeMap.getMapName() + " succeeded.");
					logger.log(Simulation.sailorInfoLevel, "Turns Used:  " + turns + "; distance traveled:  " + distTraveled);
					
					return true;
				}
				else
				{
					activeMap.moveSailorTo(dirToMove, turns);
					if(dirToMove == Directions.NORTHWEST || dirToMove == Directions.NORTHEAST || dirToMove == Directions.SOUTHEAST || dirToMove == Directions.SOUTHWEST)
						distTraveled+=Math.sqrt(2.0);
					else
						distTraveled+=1.0;
				}
			} catch (InvalidMoveException e) {
				System.out.println("Your sailor attempted to go somewhere he can't.  This simulation will now end.  ");
				logger.log(Simulation.sailorInfoLevel, "The sailor attempted to move somewhere impossible.  Simulation terminated");
				return false;
			}
			logger.log(Simulation.sailorInfoLevel, "End Turn:  " + turns);
		}
		System.out.println("The sailor exceeded the 1000 turn maximum; the ship has left.  ");
		logger.log(Simulation.sailorInfoLevel,"Simulation " + activeMap.getMapName() +  " failed:  Turn limit exceeded.  ");
		return false;
		
	}
}
